iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0
Cloud Native

AWS AI交易室實戰系列 第 22

Day 22 - 永豐 API 下單微服務開發與部署

  • 分享至 

  • xImage
  •  

~ 雲端有雲端的規則 ~

我們今天來嘗試把 api 放到 AWS Lambda 上跑
首先先修改 lambda_function.py 加入以下函式:

import shioaji as sj
import json

def lambda_handler(event, context):
    api_key = event['apiKey']
    secret_key = event['secretKey']
    if len(api_key) > 0 and len(api_key) > 0:  
        api = sj.Shioaji(simulation=True)
        accounts =  api.login(api_key, secret_key)
        if len(accounts) > 1:
            return {
                'statusCode': 200,
                'body': accounts[0].account_id
            }
        else:
            return {
                'statusCode': 404,
                'body': accounts[0].account_id
            }
    else:
        return {
            'statusCode': 400,
            'body': json.dumps('Bad Request')
        }

新增 Dockerfile 如下:

FROM public.ecr.aws/lambda/python:3.11

# Copy requirements.txt
COPY requirements.txt ${LAMBDA_TASK_ROOT}

# Copy function code
COPY lambda_function.py ${LAMBDA_TASK_ROOT}

# Install the specified packages
RUN pip install -r requirements.txt

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "lambda_function.lambda_handler" ]

requirements.txt 新增一行:

shioaji

然後在本機端建置 image,由於此 image 與之前開發用的不同,我們使用另一個名字:

$ docker build --platform linux/amd64 --no-cache \
-f Dockerfile.dev \
-t marathon-sinotrade-lambda:latest .

可以在本機端測試:

$ docker run -p 9000:8080 marathon-sinotrade-lambda:latest
# open a new console
$ curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
{"errorMessage": "'apiKey'", "errorType": "KeyError", "requestId": "c62882fa-0892-4914-aaad-5d8f19c276eb", "stackTrace": ["  File \"/var/task/lambda_function.py\", line 5, in lambda_handler\n    api_key = event['apiKey']\n"]}%

接著把它丟到 AWS ECR 上面:

# query account id
$ aws sts get-caller-identity --query "Account" --output text

# login to ECR
$ aws ecr get-login-password \
--region ap-northeast-1 | docker login \
--username AWS \
--password-stdin <account_id>.dkr.ecr.ap-northeast-1.amazonaws.com

$ aws ecr create-repository \
--repository-name marathon-sinotrade-lambda \
--image-scanning-configuration scanOnPush=true \
--image-tag-mutability MUTABLE

$ docker tag marathon-sinotrade-lambda:latest \
<account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/marathon-sinotrade-lambda:latest

$ docker push \
<account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/marathon-sinotrade-lambda:latest

建立 lambda function(使用 Day7 建立的 execution role):

$ aws lambda create-function \
  --function-name marathon-sinotrade-lambda \
  --package-type Image \
  --code ImageUri=<account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/marathon-sinotrade-lambda:latest \
  --role arn:aws:iam::<account_id>:role/marathon-lambda-ex

因為永豐 api 預設會寫檔而 lambda 會沒有寫入檔案的權限,需要加入以環境變數改變寫檔位置,還好 lambda 有 /tmp 暫存資料夾可以使用,另外預設 timeout 時間是 3 sec,我們把它改到 1 min (最長可以到 15 min):

$ aws lambda update-function-configuration \
--function-name marathon-sinotrade-lambda \
--timeout 60 \
--environment "Variables={SJ_CONTRACTS_PATH=/tmp,SJ_LOG_PATH=/tmp/shioaji.log}"

我們這是測試開發用,就不設定 vpc 了,一般來說建議設定,這隻 api 需要連外,也需要給 AWS 內部使用,建議是放在私有子網設定 NAT 連出去

預設不設定 vpc 是可以連外的,我們可以測試一下:

# payload.json
{
    "apiKey":"XXX",
    "secretKey":"XXX"
}

$ aws lambda invoke \
--function-name marathon-sinotrade-lambda \
--payload file://payload.json response.json

$ vi response.json
{"statusCode": 200, "body": <sino_account_id>}

現在我們可以改寫 lambda_handler(event, context) 來客製化我們的下單機啦!

這整個開發建置流程似乎還有需要改善的地方,總結這兩天的心得如下:

  1. 還是應該選擇 conda 管理 python x86_64 版本來建置 virtualenv 的方式開發
  2. 所有第三方 lib 應該都要放在 requirements.txt 裡面
  3. AWS Lambda 使用的 image Dockerfile 內容應該都一樣不會變

參考資料:

https://docs.aws.amazon.com/lambda/latest/dg/python-image.html#python-image-instructions
https://sinotrade.github.io/
https://docs.aws.amazon.com/cli/latest/reference/lambda/create-function.html


上一篇
Day 21 - 永豐 API 微服務開發環境建置
下一篇
Day 23 - 演算法交易 概覽
系列文
AWS AI交易室實戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言